#include <stdio.h>
#include <iostream>
#include <process.h>
#include <io.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <UrlMon.h>

#include <flv.h>

static const char *infile = NULL;
static const char *outfile = NULL;
static const char *invideo = NULL;
static const char *outvideo = NULL;
static const char *inaudio = NULL;
static const char *outaudio = NULL;
static int video_skip = 0;
static int audio_skip = 0;
static int audio_len = -1;
static int video_len = -1;	

enum {
	OP_NOOP,
	OP_MPLEX,
	OP_DMPLEX
};
static int op = OP_NOOP;

#define OPTION(flag, str)						\
	if(strcmp(argv[i], (flag)) == 0 && (i+1) < argc)		\
	{								\
		(str) = argv[++i];					\
		continue;						\
	}

#define OPERATION(flag, op, type)					\
	if(strcmp(argv[i], (flag)) == 0)				\
	{								\
		(op) = (type);						\
		continue;						\
	}
	

#define OPTION_INT(flag, str)						\
	if(strcmp(argv[i], (flag)) == 0 && (i+1) < argc)                \
        {                                                               \
		(str) = atoi(argv[++i]);                                \
		continue;						\
	}

#define WARN_FLAG							\
	printf("unknown option %s\n", argv[i]);	

void usage()
{
	printf("\n\nflv-util: usage\n");
	printf("multiplex flv files\n");
	printf("-m -vi video.flv -ai audio.flv -o out.flv\n\n");
	printf("dmplex flv files\n");
	printf("-d -i av.flv -ao audio.flv -vo video.flv\n\n");
	printf("optional parameters:\n");
	printf("-as {ms}, -vs {ms} skip audio/video by {ms} millisecs\n");
	printf("-al {ms}, -vl {ms} restrict audio/video length to {ms} millisec\n\n\n");
	exit(0);
}

void dmplex()
{
	CFlvStream *src=CFlvStream::Open(infile);
	CFlvStream *v = NULL;
	CFlvStream *a = NULL;
	CStream *sa=0;
	FlvTag tag;
	if(src == NULL)
		return;
	CStream* sv=0;
	if(outvideo != NULL)
	{
		sv = CStream::Create(STREAM_VIDEO);
		if(sv == NULL)
		{
			printf("cant create generic video stream\n");
			return;
		}
		v = CFlvStream::Create(outvideo, NULL, sv, FLV_VERSION_1);
		if(v == NULL)
			return;
	}

	if(outaudio != NULL)
	{
		sa = CStream::Create(STREAM_AUDIO);
		if(sa == NULL)
		{
			printf("cant create generic audio stream\n");
			return;
		}
			
		a = CFlvStream::Create(outaudio, CStream::Create(STREAM_AUDIO), NULL, FLV_VERSION_1);
		if(a == NULL)
			return;
	}

	while(src->ReadNextTag(&tag) == 0) 
	{
		if(tag.type == FLV_TAG_TYPE_VIDEO && v != NULL)
		{
			if(video_len > 0 && (int)tag.timestamp > video_len)
				continue;
			if(video_skip > 0 &&  (int)tag.timestamp < video_skip)
				continue;
			
			v->WriteAudioTag((int)tag.timestamp, 0,  &tag);
		}
		else if(tag.type == FLV_TAG_TYPE_AUDIO && a != NULL)
		{
			if(audio_len > 0 && (int) tag.timestamp > audio_len)
                                continue;
                        if(audio_skip > 0 &&  (int)tag.timestamp < audio_skip)
                                continue;
						
			a->WriteAudioTag(tag.timestamp, 0, &tag);
		}
	}
}

void mplex()
{
	CFlvStream *dst, *a=0, *v=0;
	CStream *sa = NULL, *sv = NULL;
	struct FlvTag ta, tv;
	int err_a = 0, err_v = 0;
	
	a = CFlvStream::Open(inaudio);
	if(a == NULL)
		return;
	v = CFlvStream::Open(invideo);
	if(v == NULL)

	printf("here\n");	
	if(a != NULL)
		sa = CStream::Create(STREAM_AUDIO);
	if(v != NULL)
		sv = CStream::Create(STREAM_VIDEO);


	dst = CFlvStream::Create(outfile, sa, sv, FLV_VERSION_1);
	if(dst == NULL)
		return;
	if(a->ReadNextTag(&ta) < 0)
		err_a = 1;
	if(v->ReadNextTag(&tv) < 0)
		err_v = 1;
	
	while(!err_a || !err_v)
	{
		if(!err_a && !err_v)
		{
			if(ta.timestamp < tv.timestamp)
			{
				dst->WriteAudioTag(ta.timestamp, 0, &ta);
				if(a->ReadNextTag(&ta) < 0)
					err_a = 1;
			}	 
			else
			{
				dst->WriteVideoTag(tv.timestamp, 0, &tv);
				if(v->ReadNextTag(&tv) < 0)
					err_v = 1;
			}
		}
		else if(!err_a && err_v)
		{
			dst->WriteAudioTag(ta.timestamp, 0, &ta);
			if(a->ReadNextTag(&ta) < 0)
				err_a = 1;
		}
		else if(err_a && !err_v)
		{
			dst->WriteVideoTag(tv.timestamp, 0, &tv);
			if(v->ReadNextTag(&tv) < 0)
				err_v = 1;
		}
	}
}


int main(int argc, char *argv[]) 
{
	int handler=-1;
	using std::cout;
	using std::endl;
	errno_t no= _sopen_s(&handler,"a.flv",O_RAW,S_ASYNCHRONOUS,P_WAIT);
	cout<<no<<endl;
	cout<<handler<<endl;
	
	return 0;
	int i;
			
	for(i = 1; i < argc; i++)
	{
		OPERATION("-d", op, OP_DMPLEX);
		OPERATION("-m", op, OP_MPLEX);
		
		OPTION("-i", infile);
		OPTION("-o", outfile);
		OPTION("-vi", invideo);
		OPTION("-ai", inaudio);
		OPTION("-vo", outvideo);
		OPTION("-ao", outaudio);
		
		OPTION_INT("-vs", video_skip);
		OPTION_INT("-as", audio_skip);
		OPTION_INT("-vl", video_len);
		OPTION_INT("-al", audio_len);
	}
	
	switch(op)
	{
	case OP_DMPLEX:
		if(infile == NULL)
			usage();
		dmplex();
		break;
	case OP_MPLEX:
		if(invideo == NULL || inaudio == NULL || outfile == NULL)
			usage();
		mplex();
		break;
	default:
		usage();
	}
	return 0;
}